package com.slj.comm.advice;

import com.slj.comm.responce.R;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

import java.util.Set;

/**
 * @author CC
 * @version 1.0
 * @description: 全局响应处理
 * @date 2025/9/11 16:16
 */
//@RestControllerAdvice// 控制器增强 // 组合了 @ControllerAdvice 和 @ResponseBody
public class GlobalResponseHandler implements ResponseBodyAdvice<Object> {
    // 排除的路径前缀  解决springdoc无法打开
    private static final Set<String> EXCLUDE_PATHS = Set.of(
            "/swagger-ui",
            "/v3/api-docs",
            "/webjars/",
            "/doc.html",      // 如果使用了 knife4j
            "/swagger-resources",
            "/configuration/"
    );
    @Override
    public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
        // 1. 如果已经是 R 类型，不包装
        if (returnType.getParameterType().equals(R.class)) {
            return false;
        }
        // 注意：这里不能只靠 returnType 判断，还要结合路径
        return true;
    }

    @Override
    public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
        // 2. 检查请求路径，如果是静态资源或 swagger 路径，直接返回原 body
        String path = request.getURI().getPath();
        for (String excludePath : EXCLUDE_PATHS) {
            if (path.startsWith(excludePath)) {
                return body; // 不包装，直接放行
            }
        }

        // 3. 处理 String 类型（避免 Jackson 序列化问题）
        if (body instanceof String) {
            // 注意：String 不能直接返回 JSON 字符串，否则会报错
            // 所以我们让 Jackson 把 R 序列化为 JSON 字符串输出
            response.getHeaders().setContentType(MediaType.APPLICATION_JSON);
            return R.success(body);
        }

        // 4. 其他对象包装为 R.success
        return R.success(body);
    }
}
